package org.kabeja.math;

import org.kabeja.dxf.helpers.Point;
import org.kabeja.dxf.helpers.Vector;

/**
 * @author shutao
 * @since 2022/4/24 16:27
 */
public class MathUtils {
    public static final double DISTANCE_DELTA = 1.0E-5D;

    public MathUtils() {
    }

    public static double scalarProduct(Vector var0, Vector var1) {
        return var0.getX() * var1.getX() + var0.getY() * var1.getY() + var0.getZ() * var1.getZ();
    }

    public static double absoluteValue(Vector var0) {
        return Math.sqrt(Math.pow(var0.getX(), 2.0D) + Math.pow(var0.getY(), 2.0D) + Math.pow(var0.getZ(), 2.0D));
    }

    public static Vector crossProduct(Vector var0, Vector var1) {
        Vector var2 = new Vector();
        var2.setX(var0.getY() * var1.getZ() - var0.getZ() * var1.getY());
        var2.setY(var0.getZ() * var1.getX() - var0.getX() * var1.getZ());
        var2.setZ(var0.getX() * var1.getY() - var0.getY() * var1.getX());
        return var2;
    }

    public static Vector scaleVector(Vector var0, double var1) {
        Vector var3 = new Vector();
        var3.setX(var0.getX() * var1);
        var3.setY(var0.getY() * var1);
        var3.setZ(var0.getZ() * var1);
        return var3;
    }

    public static Point getPointOfStraightLine(Point var0, Vector var1, double var2) {
        Point var4 = new Point();
        Vector var5 = scaleVector(var1, var2);
        var4.setX(var0.getX() + var5.getX());
        var4.setY(var0.getY() + var5.getY());
        var4.setZ(var0.getZ() + var5.getZ());
        return var4;
    }

    public static Vector getVector(Point var0, Point var1) {
        Vector var2 = new Vector();
        var2.setX(var1.getX() - var0.getX());
        var2.setY(var1.getY() - var0.getY());
        var2.setZ(var1.getZ() - var0.getZ());
        return var2;
    }

    public static Point getIntersection(Point var0, Vector var1, Point var2, Vector var3) {
        Vector var4 = crossProduct(var1, var3);
        Vector var5 = crossProduct(getVector(var0, var2), var3);
        double var6 = 0.0D;
        if (var4.getZ() != 0.0D) {
            var6 = var5.getZ() / var4.getZ();
        } else if (var4.getY() != 0.0D) {
            var6 = var5.getY() / var4.getY();
        } else if (var4.getX() != 0.0D) {
            var6 = var5.getX() / var4.getX();
        }

        return getPointOfStraightLine(var0, var1, var6);
    }

    public static double distance(Point var0, Point var1) {
        return Math.sqrt(Math.pow(var1.getX() - var0.getX(), 2.0D) + Math.pow(var1.getY() - var0.getY(), 2.0D) + Math.pow(var1.getZ() - var0.getZ(), 2.0D));
    }

    public static double getAngle(Vector var0, Vector var1) {
        double var2 = scalarProduct(var0, var1) / (absoluteValue(var0) * absoluteValue(var1));
        return Math.acos(var2);
    }

    public static Point rotatePoint(Point p0, Point p1, double radian) {
        Point point = new Point();

        point.setX((p1.getX() - p0.getX()) * Math.cos(radian) - (p1.getY() - p0.getY()) * Math.sin(radian) + p0.getX());
        point.setY((p1.getX() - p0.getX()) * Math.sin(radian) + (p1.getY() - p0.getY()) * Math.cos(radian) + p0.getY());
        return point;
    }

    public static Vector normalize(Vector var0) {
        double var1 = absoluteValue(var0);
        return scaleVector(var0, 1.0D / var1);
    }

    public static int getQuadrant(Point var0, Point var1) {
        if (var0.getX() < var1.getX()) {
            return var0.getY() >= var1.getY() ? 1 : 2;
        } else {
            return var0.getY() >= var1.getY() ? 0 : 3;
        }
    }

    public static int getQuadrant(double var0) {
        if (var0 > 360.0D) {
            var0 -= Math.floor(var0 / 360.0D) * 360.0D;
        }

        if (var0 >= 0.0D && var0 < 90.0D) {
            return 0;
        } else if (var0 >= 90.0D && var0 < 180.0D) {
            return 1;
        } else {
            return var0 >= 180.0D && var0 < 270.0D ? 2 : 3;
        }
    }

    public static double getDirectionAngle(Vector var0) {
        double var1 = absoluteValue(var0);
        if (var0.getX() < 0.0D && var0.getY() < 0.0D) {
            return Math.toDegrees(Math.acos(Math.abs(var0.getX() / var1))) + 180.0D;
        } else {
            return var0.getX() != 0.0D && !(var0.getY() < 0.0D) ? Math.toDegrees(Math.acos(var0.getX() / var1)) : Math.toDegrees(Math.asin(var0.getY() / var1));
        }
    }

    public static Vector invertDirection(Vector var0) {
        return scaleVector(var0, -1.0D);
    }

    public static double[][] multiplyMatrixByMatrix(double[][] var0, double[][] var1) throws IllegalArgumentException {
        if (var0[0].length != var1.length) {
            throw new IllegalArgumentException("Cannot multiply a with b, columns of a != rows of b. ");
        } else {
            double[][] var2 = new double[var0.length][var1[0].length];

            for(int var3 = 0; var3 < var0.length; ++var3) {
                for(int var4 = 0; var4 < var1[0].length; ++var4) {
                    for(int var5 = 0; var5 < var1.length; ++var5) {
                        var2[var3][var4] += var0[var3][var5] * var1[var4][var5];
                    }
                }
            }

            return var2;
        }
    }

    public static double[] multiplyMatrixByVector(double[][] var0, double[] var1) throws IllegalArgumentException {
        if (var0[0].length != var1.length) {
            throw new IllegalArgumentException("Cannot multiply a with v, columns of a != rows of v. ");
        } else {
            double[] var2 = new double[var0.length];

            for(int var3 = 0; var3 < var0.length; ++var3) {
                for(int var4 = 0; var4 < var1.length; ++var4) {
                    var2[var3] += var0[var3][var4] * var1[var4];
                }
            }

            return var2;
        }
    }

    public static Vector subtractVectorByVector(Vector var0, Vector var1) {
        Vector var2 = new Vector();
        var2.setX(var0.getX() - var1.getX());
        var2.setY(var0.getY() - var1.getY());
        var2.setZ(var0.getZ() - var1.getZ());
        return var2;
    }

    public static Vector addVectorToVector(Vector var0, Vector var1) {
        Vector var2 = new Vector();
        var2.setX(var0.getX() + var1.getX());
        var2.setY(var0.getY() + var1.getY());
        var2.setZ(var0.getZ() + var1.getZ());
        return var2;
    }
}
